#include <stdio.h>
#include <unistd.h> // execl()
#include <stdlib.h> // exit()
#include <assert.h> 
#include <sys/wait.h> // wait() || waitpid()
#include <sys/types.h>

// 单进程替换(一般不会在父进程替换)

//int main() 
//{
//
//    printf("当前进程正在运行\n");
//    // int execl(const char *path, const char *arg, ...);
//    execl("/usr/bin/ls"/*要执行那个程序*/,"ls",NULL/*想怎么执行*/);
//
//    // ececl调用失败了，就是没有替换成功，就是没有完成进程替换，所以 后面的printf就可以执行
//    // 那么为什么exec* 为什么没有成功返回值呢？ 因为成功了，就和接下来的代码无关了
//    //execl("/usr/bin/lsssdkjfksjd"/*要执行那个程序*/,"ls",NULL/*想怎么执行*/);
//
//    perror("execl");  // 打印错误原因
//    // 为什么这里的printf没有执行呢？？？？ printf是代码，是在execl之后执行的
//    // execl执行完毕的时候，代码和数据已经被指定程序的代码和数据替换了，开始执行新的程序的代码了，所以printg就无法执行了
//    printf("当前进程结束运行\n");
//
//    exit(1);
//    
//    return 0;
//}


// 多进程替换（在子进程使用进程替换）

int main()
{
    printf("进程正在运行\n");
    pid_t id = fork();
    assert(id != -1);
    
    // 子进程
    if(id ==0)
    {
        sleep(1);
        //------------------------   1.execl --------------------------------
        // 这里的l是表示将参数一个一个的传入exec*
        // execl("/usr/bin/ls","ls",NULL);
        
        //------------------------   2.execlp --------------------------------
        // execlp ：如何找到程序的可能，带p字符的函数，不用告诉我程序的路径，你只要告诉我是谁，会自动在环境变量PATH，进行可执行程序的查找!
        // execlp("ls","ls","-a",NULL);

        //------------------------   3.execv --------------------------------
        // char *const argv_[] = {"ls", "-a", "-l", NULL};
        // execv("/usr/bin/ls",argv_);

        
        //------------------------   4.execle --------------------------------
        //(1) 这种子进程只会拥有自定义环境变量
        // char *const envp_[] = {(char*)"MYENV=111265762",NULL};// 自定义环境变量
        // execle("./mybin","./mybin",NULL,envp_);
        
        //(2) 把自定义环境变量 导入系统环境变量  使用environ可以使子进程继承系统环境变量
        putenv("MYENV=128475847390");
        extern char **environ;
        execle("./mybin","mybin",NULL,environ);

        // 执行完毕就退出
        exit(1);
    }

    // 父进程
    int status = 0;
    pid_t ret = waitpid(id,&status,0);

    if(ret > 0) printf("wait success：exit code: %d，sig：%d\n",(status>>8)&0xFF,status & 0x7F);

    return 0;
}

